using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using Gadgeteer.Modules;

/*
 * Original Gadgeteer framework Copyright (c) Microsoft Corporation. (http://gadgeteer.codeplex.com/)
 * 
 * Gadgeteer Light made by Stefan Thoolen (http://gadgeteerlight.codeplex.com/)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
namespace Gadgeteer
{
    public class Socket
    {
        /// <summary>The number of this socket</summary>
        public int SocketNumber { get; private set; }

        /// <summary>Name of the socket</summary>
        public string Name { get; private set; }

        /// <summary>Serial port linked to the socket</summary>
        public string SerialPortName { get { return Board.Hardware.GetSerial(this.SocketNumber); } }

        /// <summary>Contains all socket pins</summary>
        public Cpu.Pin[] CpuPins = new Cpu.Pin[11];

        /// <summary>
        /// Returns a socket
        /// </summary>
        /// <param name="socketNumber">The socket number</param>
        /// <param name="throwExceptionIfSocketNumberInvalid">Not in use</param>
        /// <param name="module">Not in use</param>
        /// <param name="socketLabel">Not in use</param>
        /// <returns></returns>
        public static Socket GetSocket(int socketNumber, bool throwExceptionIfSocketNumberInvalid, Module module, string socketLabel)
        {
            return new Socket(socketNumber, socketLabel);
        }

        /// <summary>Creates a new socket</summary>
        /// <param name="socketNumber">The number of the socket</param>
        /// <param name="name">Name of the socket</param>
        internal Socket(int socketNumber, string name)
        {
            this.SocketNumber = socketNumber;
            this.Name = name;
            for (int i = 0; i < 11; ++i)
                this.CpuPins[i] = Board.Hardware.GetPin(SocketNumber, i);
        }

        /// <summary>Checks if the socket supports the given type</summary>
        /// <param name="type">Socket type</param>
        /// <returns>true if it's supported</returns>
        public bool SupportsType(char type)
        {
            return Board.Hardware.GetSupported(this.SocketNumber, type);
        }

        /// <summary>Checks if the socket supports the given type</summary>
        /// <param name="type">Socket type</param>
        /// <param name="module">The module</param>
        public void EnsureTypeIsSupported(char type, Module module)
        {
            if (!SupportsType(type))
                throw new InvalidSocketException("Socket " + Name + " does not support type '" + type + "'" + (module != null ? "  required by " + module + " module." : "."));
        }

        /// <summary>Checks if the socket supports one of the given types</summary>
        /// <param name="types">Socket types</param>
        /// <param name="module">The module</param>
        public void EnsureTypeIsSupported(char[] types, Module module)
        {
            foreach (char type in types)
                if (SupportsType(type)) return;

            throw new InvalidSocketException("Socket " + Name + " does not support one of the types '" + new String(types) + "'" + (module != null ? "  required by " + module + " module." : "."));
        }

        /// <summary>Pins on the socket</summary>
        public enum Pin
        {
            Three = 3,
            Four = 4,
            Five = 5,
            Six = 6,
            Seven = 7,
            Eight = 8,
            Nine = 9
        }

        public class InvalidSocketException : ArgumentException
        {
            public InvalidSocketException(String message) : base(message) { }
            public InvalidSocketException(String message, Exception e) : base(message, e) { }
        }
    }
}
